using UnityEngine;

public class TableTennisRemotePlayerRacket : TableTennisPlayerBase, RemotePlayerMessageHandlers
{
	private bool isInServe;

	public Transform racket;

	protected float racketY;

	protected Vector3 desiredPosition;

	protected float racketSpeed = 20f;

	protected GravityBallFlight serveFlight = new GravityBallFlight();

	public PhysicsBall ball { get; protected set; }

	public override bool IsInServe()
	{
		return isInServe;
	}

	public override void Init(int teamTag, int tableSide, TableTennisMatchController match, bool canAlwaysHit)
	{
		base.Init(teamTag, tableSide, match, canAlwaysHit);
		racket.rotation = Quaternion.AngleAxis(-70f, Vector3.forward);
		racketY = Table.tabletopy + 0.125f;
		desiredPosition = new Vector3(0f, racketY, (float)tableSide * Table.halfLength);
	}

	public void SetPosition(MRemotePosInfo racketPos)
	{
		Vector3 vector = MultiplayerMatchController.RemoteToLocalPos(racketPos.playerPosition);
		Vector3 vector2 = MultiplayerMatchController.RemoteToLocalPos(racketPos.ballPos);
		TableTennisPlayerBase player = base.match.GetPlayer(0);
		desiredPosition = vector;
		PhysicsBall physicsBall = base.match.ball;
		if (physicsBall.isBallInGame && physicsBall.playerThatHitBall == player)
		{
			float num = physicsBall.flightSequence.flightDuration * 0.5f;
			FlightSequence.FlightPlanStage stageThatStartsFromTableSide = physicsBall.flightSequence.GetStageThatStartsFromTableSide(base.tableSide);
			if (stageThatStartsFromTableSide != null)
			{
				num = physicsBall.flightSequence.GetTimeToStage(stageThatStartsFromTableSide);
			}
			desiredPosition = Vector3.Lerp(vector, vector - vector2 + physicsBall.position, physicsBall.flightSequence.flightTime / num);
		}
		desiredPosition.y = racketY;
	}

	public void HitBall(PhysicsBall ball, MHitBall hitBall)
	{
		isInServe = false;
		this.ball = ball;
		ball.position = hitBall.ballPosition;
		desiredPosition = new Vector3(hitBall.ballPosition.x, racket.position.y, hitBall.ballPosition.z);
		HitBall(hitBall.landingPosition, hitBall.heightAboveNet, hitBall.timeToLand, hitBall.spinx, hitBall.spiny, hitBall.isServe, hitBall.useNormalTime, hitBall.airResistance, hitBall.rebound, hitBall.racketTimeScale);
	}

	public HitBallParamsPhysicsFlight HitBall(PhysicsBall ball, MHitBallAvatar hitBall)
	{
		GGDebug.DebugLog("Not implemented for this player");
		return default(HitBallParamsPhysicsFlight);
	}

	public void SwipeToHit(MStartSwipe swipe, PhysicsBall ball)
	{
		GGDebug.DebugLog("Not implemented for this player");
	}

	public void DoStartServe(MStartServeToss serveToss)
	{
		GGDebug.DebugLog("Not implemented for this player");
	}

	public float ServeTimeOffsetFraction()
	{
		return 0f;
	}

	public void HitBall(Vector3 landingPos, float heightAboveNet, float timeToLand, float spinx, float spiny, bool isServe, bool useNormalTime = true, float airResistance = 0f, float rebound = 1f, float racketTimeScale = 1f)
	{
		if (isServe || ball.flightSequence.isActive || ball.isBallInGame)
		{
			HitParameters hitParams = default(HitParameters);
			if (isServe)
			{
				AnalyticFlightTrajectory.SequenceSimulationParams sim = AnalyticFlightTrajectory.SequenceSimulationParams.DefaultRecordFlightParams(serveFlight, ball, landingPos, heightAboveNet, timeToLand, spinx, 0f);
				sim.airResistance = airResistance;
				sim.rebound = rebound;
				AnalyticFlightTrajectory instance = Singleton<AnalyticFlightTrajectory>.instance;
				instance.HitServe(ball.flightSequence, sim);
				ball.flightSequence.Reset();
				isInServe = false;
			}
			else
			{
				AnalyticFlightTrajectory.SequenceSimulationParams sim2 = AnalyticFlightTrajectory.SequenceSimulationParams.DefaultRecordFlightParams(serveFlight, ball, landingPos, heightAboveNet, timeToLand, spinx, spiny);
				sim2.useNormalTime = useNormalTime;
				sim2.airResistance = airResistance;
				sim2.rebound = rebound;
				AnalyticFlightTrajectory instance2 = Singleton<AnalyticFlightTrajectory>.instance;
				instance2.HitBall(ball.flightSequence, sim2);
				ball.flightSequence.Reset();
			}
			HitBallParams hitBallParams = default(HitBallParams);
			hitBallParams.ballPosition = ball.position;
			hitBallParams.landingPosition = landingPos;
			hitBallParams.heightAboveNet = heightAboveNet;
			hitBallParams.timeToLand = timeToLand;
			hitBallParams.spinx = spinx;
			hitBallParams.spiny = spiny;
			hitBallParams.isServe = isServe;
			hitBallParams.useNormalTime = useNormalTime;
			hitBallParams.airResistance = airResistance;
			hitBallParams.rebound = rebound;
			hitBallParams.racketTimeScale = racketTimeScale;
			ball.ResetTimescale();
			ball.racketTimeScale = racketTimeScale;
			ball.hitParams = hitParams;
			ball.isServeBall = isServe;
			ball.playerThatHitBall = this;
			ball = null;
			base.match.OnPlayerHitBall(this, hitBallParams);
			isInServe = false;
			base.match.ui.ballFollower.fire.SetActive(false);
		}
	}

	private void Update()
	{
		racket.position = Vector3.Lerp(racket.position, desiredPosition, Time.deltaTime * racketSpeed);
		PhysicsBall physicsBall = base.match.ball;
		float num = physicsBall.position.x - racket.position.x;
		racket.rotation = Quaternion.Lerp(racket.rotation, Quaternion.AngleAxis((float)MathEx.SignZeroPositive(num) * Mathf.Lerp(0f, 1f, 4f * Mathf.Abs(num) / Table.halfwidth) * -70f, Vector3.forward), Time.deltaTime * 20f);
		if (!(physicsBall == null) && isInServe)
		{
			UpdateServeBall();
		}
	}

	private void UpdateServeBall()
	{
		Vector3 position = racket.position;
		position.x = Mathf.Clamp(position.x, 0f - Table.halfwidth, Table.halfwidth);
		position.z = (float)base.tableSide * Table.halfLength;
		serveFlight.flightTime = Mathf.Repeat(serveFlight.flightTime + Time.deltaTime, 2f * serveFlight.apexTime);
		position.y = serveFlight.PositionAt(serveFlight.flightTime).y;
		ball.position = position;
	}

	public override void BallRemovedFromGame()
	{
		ball = null;
		isInServe = false;
	}

	public override void StartServe(PhysicsBall ball)
	{
		GGDebug.DebugLog("Remote Start Serve");
		this.ball = ball;
		this.ball.SetKinematic(true);
		Vector3 position = racket.position;
		position.y = Table.tabletopy;
		position.x = Mathf.Clamp(position.x, 0f - Table.halfwidth, Table.halfwidth);
		ball.position = position;
		FlightParams flightParams = default(FlightParams);
		flightParams.position = position;
		flightParams.velocity = ParabolicFlight.initialVelocityForSimpleCase(position, position, Table.tabletopy + 0.3f);
		flightParams.angularVelocity = Vector3.zero;
		FlightParams initialConditions = flightParams;
		serveFlight.gravity = Physics.gravity;
		serveFlight.SetInitialConditions(initialConditions, null);
		serveFlight.Reset();
		isInServe = true;
	}

	public override void AwaitServe()
	{
		ball = null;
	}

	public override void ReceiveBall(PhysicsBall ball)
	{
		this.ball = ball;
		this.ball.SetKinematic(true);
	}
}
